package proto_logic

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"text/template"

	"google.golang.org/protobuf/compiler/protogen"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/types/pluginpb"
)

type RpcMethod struct {
	Name   string
	Input  string
	Output string
}
type RpcService struct {
	Name    string
	Methods []RpcMethod
}
type MapRcpService map[string]*RpcService

var map_serices MapRcpService

type RpcPackage struct {
	Packages []string
	Names    string
}

var rpc_package RpcPackage

func Deal() {
	CollectPlugins()
	// Write()
	Do1()
}

func Do1() {
	filename := "../proto_out/proto_actor.fruit.go"
	file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println("文件打开失败", err)
	}
	defer file.Close()
	file_tmp := "./proto_logic/proto_global.go.tmp"

	t1, err := template.New("proto_global.go.tmp").Funcs(template.FuncMap{
		"IsStringContains": func(str string, find string) bool {
			return strings.Contains(str, find)
		},
		"GetMethod": func(str string, find string, replace string) string {
			if strings.Contains(str, find) {
				data := strings.Split(str, find)
				if len(data) > 1 {
					return replace + data[1]
				}
			} else {
				return str
			}
			return ""
		},
		"StringConcat": func(a, b string) string {
			return a + b
		},
	}).ParseFiles(file_tmp)
	// t1, err := template.ParseFiles(file_tmp)
	if err != nil {
		panic(err)
	}

	t1.Execute(file, map_serices)
}

func CollectPlugins() MapRcpService {
	input, _ := ioutil.ReadAll(os.Stdin)
	var req pluginpb.CodeGeneratorRequest
	proto.Unmarshal(input, &req)

	opts := protogen.Options{}
	plugin, err := opts.New(&req)
	if err != nil {
		panic(err)
	}

	map_serices = make(MapRcpService, 0)

	for _, file := range plugin.Files {
		rpc_package.Packages = append(rpc_package.Packages, string(file.GoPackageName))
		for _, v := range file.Services {
			service_name := string(v.Desc.FullName())
			service_data, exists := map_serices[service_name]
			if !exists {
				map_serices[service_name] = &RpcService{
					Name: service_name,
				}
				service_data, exists = map_serices[service_name]
				// fmt.Println("sss2", exists, service_data.Name)
			}

			for _, method := range v.Methods {
				service_data.Methods = append(service_data.Methods, RpcMethod{
					Name:   string(method.Desc.Name()),
					Input:  string(method.Input.Desc.Name()),
					Output: string(method.Output.Desc.Name()),
				})

			}
		}
	}

	return map_serices
}
